package com.swallow.auth.infrastructure.acl.oauth2.support.sms;

import com.swallow.auth.infrastructure.acl.oauth2.constants.SecurityConstants;
import com.swallow.auth.infrastructure.acl.oauth2.utils.SecurityUtils;
import jakarta.servlet.http.HttpServletRequest;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.oauth2.core.AuthorizationGrantType;
import org.springframework.security.oauth2.core.OAuth2ErrorCodes;
import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames;
import org.springframework.security.web.authentication.AuthenticationConverter;
import org.springframework.util.MultiValueMap;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @author: yangjie.deng@resico.cn
 * @since: 2024-05-15 09:31:14
 * @version: v1.0.0
 * @describe: 短信验证码登录转换器
 */
public class SmsGrantAuthenticationConverter implements AuthenticationConverter {
    @Override
    public Authentication convert(HttpServletRequest request) {
        String grantType = request.getParameter(OAuth2ParameterNames.GRANT_TYPE);

        if (!StringUtils.equals(SecurityConstants.GRANT_TYPE_SMS_CODE, grantType)) {
            return null;
        }
        MultiValueMap<String, String> parameters = SecurityUtils.getParameters(request);

        // scope (OPTIONAL)
        String scope = parameters.getFirst(OAuth2ParameterNames.SCOPE);

        if (StringUtils.isNotBlank(scope) && parameters.get(OAuth2ParameterNames.SCOPE).size() != 1) {
            SecurityUtils.throwError( OAuth2ErrorCodes.INVALID_REQUEST, "短信登录: 授权范围不正确");
        }
        Set<String> requestedScopes = null;
        if (StringUtils.isNotBlank(scope)) {
            requestedScopes = Stream.of(scope.split(",")).collect(Collectors.toSet());
        }

        // 手机号
        String mobile = parameters.getFirst(SecurityConstants.SMS_LOGIN_MOBILE_PARAM);
        if (StringUtils.isBlank(mobile) || parameters.get(SecurityConstants.SMS_LOGIN_MOBILE_PARAM).size() != 1) {
            SecurityUtils.throwError( OAuth2ErrorCodes.INVALID_REQUEST, "短信登录: 手机号不能为空");
        }

        // 短信验证码
        String captcha = parameters.getFirst(SecurityConstants.SMS_LOGIN_CAPTCHA_PARAM);
        if (StringUtils.isBlank(captcha) || parameters.get(SecurityConstants.SMS_LOGIN_CAPTCHA_PARAM).size() != 1) {
            SecurityUtils.throwError( OAuth2ErrorCodes.INVALID_REQUEST, "短信登录: 验证码不能为空");
        }

        // 提取附加参数
        Map<String, Object> additionalParameters = new HashMap<>();

        parameters.entrySet()
                  .stream()
                  .filter(entry -> !StringUtils.equalsAny(entry.getKey(), OAuth2ParameterNames.GRANT_TYPE,OAuth2ParameterNames.CLIENT_ID))
                  .forEach(entry -> additionalParameters.put(entry.getKey(), entry.getValue().getFirst()));

        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();

        return new SmsGrantAuthenticationToken(authentication.getAuthorities(),
                                               requestedScopes,
                                               authentication,
                                               additionalParameters,
                                               new AuthorizationGrantType(SecurityConstants.GRANT_TYPE_SMS_CODE));
    }
}
